package com.celebriosoftware.client;

import java.util.Locale;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.DownloadManager;
import android.content.Context;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.celebriosoftware.celebrioclient.R;
import com.celebriosoftware.client.fragments.AppFragment;
import com.celebriosoftware.client.fragments.DesktopFragment;
import com.celebriosoftware.client.fragments.LoginFragment;
import com.celebriosoftware.client.receiver.DownloadReceiver;

@SuppressLint("SetJavaScriptEnabled")
public class MainActivity extends FragmentActivity {
	//public static final String CELEBRIO_URL = "http://testing.celebriosoftware.com";
	public static final String CELEBRIO_URL = "http://system.celebriosoftware.com";
	//public static final String CELEBRIO_URL = "http://147.251.44.82/celebrio/document_root/";
	//public static final String CELEBRIO_URL = "http://192.168.1.121/celebrio/document_root/";
	//public static final String CELEBRIO_URL = "http://192.168.1.111/celebrio/document_root";

	public static final String CELEBRIO_CLIENT = "CelebrioClient-Android";
	public static final String BROWSER_DEFAULT_URL = "http://www.google.com";
	
	public Dialog splashDialog;	//first run loading screen
	private Dialog connectionLostDialog;	//connection lost screen
	private Dialog loadingDialog;
	
	private onStartNetworkCheckTask onStartNetworkCheckTask;	//task that checks connection on start
	public PeriodicNetworkCheckTask periodicNetworkCheckTask;	//if connection is lost, this rechecks periodically
	private Handler loadingHandler = new Handler();	//used for task that animates dots on loading screen
	private Handler connectionLostHandler = new Handler(); //used for task that animates dots on connection lost screen
	public String lastUri;		//remembers uri if we lose connection so that it can be recovered
	
	//public Activity browserActivity = null;
	private NetworkManager manager;
	
	//Used for hiding bottom tablet controls panel
	private RelativeLayout mainLayout;
	private final Handler rHandler = new Handler();
	private Repeater repeater;
	
	private boolean firstStart;

	private DownloadReceiver downloadReceiver;
	
	private Activity activity;
	private Fragment loginFragment;
	private Fragment desktopFragment;
	private SparseArray<Fragment> apps = new SparseArray<Fragment>();
	private Fragment currentFragment=null;
	public static SparseArray<Drawable> appsIcons= new SparseArray<Drawable>(); //Stores app icons
	public static boolean backgroundIsOK=false;
	public static String backgroundURL;
	public static Drawable background;
	
	private int counter;
	private String one = " .";
	private String two = " . .";
	private String three = " . . .";
	private String four = " . . . .";
	private String five = " . . . . .";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		firstStart = true;
		backgroundIsOK=false;
		lastUri=CELEBRIO_URL;
		if(background==null) {
			background=getResources().getDrawable( R.drawable.wall );	
		}		
		showSplashScreen(); //loading... screen
		setContentView(R.layout.activity_main);
		
		//Hiding bottom tablet control panel
		mainLayout =((RelativeLayout) findViewById(R.id.MainLayout));
		if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
			repeater=new Repeater();
			rHandler.postDelayed(repeater, 100);
		}
		Window window = getWindow();
		window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		manager = new NetworkManager(connectivityManager);

		activity = this;

		Log.i("TRACE", "onCreate");
	}

	@Override
	public void onStart() {
		super.onStart();
		//Check if we can connect and load the page
		onStartNetworkCheckTask = new onStartNetworkCheckTask();
		onStartNetworkCheckTask.execute();
		Log.i("TRACE", "onStart");
	}
	
	public void startPeriodicNetworkChecking() {
		if(periodicNetworkCheckTask==null) {
			removeSplashScreen();
			periodicNetworkCheckTask = new PeriodicNetworkCheckTask();
			periodicNetworkCheckTask.execute();			
		}
	}
	
	private class onStartNetworkCheckTask extends AsyncTask<Void, Void, Boolean> {
		protected Boolean doInBackground(Void... voids) {
		 	return manager.isNetworkAvailable();
	    }
	     
	    protected void onPostExecute(Boolean result) {
	    	if (!result) {	//fail, start checking periodically (has own screen)
	    		startPeriodicNetworkChecking();
	 		}
	    	else if(firstStart) { //go to login page
	    		Log.i("celebrio-android", "FIRST START");
	    		FragmentManager fragmentManager = getSupportFragmentManager();
	    		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
	    		
	    		loginFragment = new LoginFragment();
	    		currentFragment=loginFragment;
	    		fragmentTransaction.add(R.id.MainLayout, loginFragment);
	    		fragmentTransaction.commit();
	    		firstStart=false;
	    	}
	    	onStartNetworkCheckTask=null;
	    }
		@Override
	    protected void onCancelled(Boolean result) { //app stopping
	    	 onStartNetworkCheckTask=null;
	    }
	}
	
	private class PeriodicNetworkCheckTask extends AsyncTask<Void, Void, Boolean> {
		protected Boolean doInBackground(Void... voids) {
			runOnUiThread(new Runnable() {
				public void run() {
					showConnectionLostDialog();
				}
	    	});	    	 
	 	 	SystemClock.sleep(5000);
	    	Boolean result = manager.isNetworkAvailable();
	        return result;
	    }
		protected void onPostExecute(Boolean result) {
			if (!result) {	//still no network, check again later
				periodicNetworkCheckTask = new PeriodicNetworkCheckTask();
				periodicNetworkCheckTask.execute();
			}
			else {	//success, load last page
				periodicNetworkCheckTask=null;
				removeConnectionLostDialog();
				if(firstStart) {
		    		FragmentManager fragmentManager = getSupportFragmentManager();
		    		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		    		
		    		Fragment loginFragment = new LoginFragment();
		    		currentFragment=loginFragment;
		    		fragmentTransaction.add(R.id.MainLayout, loginFragment);
		    		fragmentTransaction.commit();
		    		firstStart=false;
		    	}
				else {
					if(currentFragment!=null && currentFragment.getView().findViewById(R.id.web_engine)!=null) {
						((WebView) currentFragment.getView().findViewById(R.id.web_engine)).loadUrl(lastUri);
						lastUri=CELEBRIO_URL;
					}
				}
			}
		}
		@Override
	    protected void onCancelled(Boolean result) { //app stopping
	    	 periodicNetworkCheckTask=null;
	    	 removeConnectionLostDialog();
	    }
	}

	@SuppressLint("InlinedApi")
	@Override
	public void onResume() {
		super.onResume();
		
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
			if(downloadReceiver==null) {
				IntentFilter downloadFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
				downloadReceiver = new DownloadReceiver(activity);
				registerReceiver(downloadReceiver, downloadFilter);
			}
		}
		
		Log.i("TRACE", "onResume");
	}

	@Override
	public void onPause(){
		super.onPause();
	    Log.i("TRACE", "onPause");
	}
	
	@Override
	protected void onStop() {
		super.onStop();
	    if(onStartNetworkCheckTask!=null) {
	    	onStartNetworkCheckTask.cancel(true);
	    }
	    if(periodicNetworkCheckTask!=null) {
	    	periodicNetworkCheckTask.cancel(true);
	    }
	};
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		removeSplashScreen();
		removeConnectionLostDialog();
		unregisterReceiver(downloadReceiver);
		Log.i("TRACE", "onDestroy");
	}
	
/*	whats this for??
 * @Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_settings:
			/engine.loadUrl("javascript:$(\"#Settings\").trigger(\"click\");");
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}*/

	@SuppressLint("NewApi")
	public void showLoadingDialog(String title, Drawable icon) {
    	if(loadingDialog==null) {
    		loadingDialog = new Dialog(this, R.style.SplashScreenTheme);
    		loadingDialog.setContentView(R.layout.loading_screen);
    		View background = loadingDialog.findViewById(R.id.LoadAnimationContainer);
			if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
				background.setBackgroundDrawable(MainActivity.background);
			} else {
				background.setBackground(MainActivity.background);
			}
    		loadingDialog.setCancelable(false);
    		LinearLayout rightfooter = (LinearLayout) loadingDialog.findViewById(R.id.bottomRightBar);
			rightfooter.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					startDesktop();
					removeLoadingDialog();
				}
			});
			if(icon!=null) {
				((ImageView) loadingDialog.findViewById(R.id.LoadAnimationLogo)).setImageDrawable(icon);
			}
			else {
				((ImageView) loadingDialog.findViewById(R.id.LoadAnimationLogo)).setImageResource(R.drawable.registration);
			}
	    	TextView label = (TextView) loadingDialog.findViewById(R.id.loadingLabel);
	    	label.setText(title);
	    	ImageView spinner = (ImageView) loadingDialog.findViewById(R.id.LoadAnimationSpinner);
			spinner.startAnimation(AnimationUtils.loadAnimation(activity, R.anim.animation));
	    	loadingDialog.show();
	    	
    	}
    }
    public void removeLoadingDialog() {
	    if (loadingDialog != null) {
	    	ImageView spinner = (ImageView) loadingDialog.findViewById(R.id.LoadAnimationSpinner);
	    	spinner.clearAnimation();
	    	loadingDialog.dismiss();
	    	loadingDialog = null;
	    }
    }	
	   
    private void showConnectionLostDialog() {
    	if(connectionLostDialog==null) {
	    	connectionLostDialog = new Dialog(this, R.style.SplashScreenTheme);
	    	connectionLostDialog.setContentView(R.layout.connection_lost_screen);
	    	connectionLostDialog.setCancelable(false);
	    	Button shutdownButton = (Button) connectionLostDialog.findViewById(R.id.connection_lost_shutdown_button);
			shutdownButton.setOnClickListener(
					new View.OnClickListener() { 
						@Override
						public void onClick(View v) {
							removeConnectionLostDialog();
							finish(); 
						}
					}
			);
	    	Button retryButton = (Button) connectionLostDialog.findViewById(R.id.connection_lost_retry_button);
			retryButton.setOnClickListener(
					new View.OnClickListener() { 
						@Override
						public void onClick(View v) {
							removeConnectionLostDialog();
							showConnectionLostDialog();
						}
					}
			);
	    	
	    	connectionLostDialog.show();
	
		    counter = 1;
		    connectionLostHandler.postDelayed(animateConnectionLostScreen, 200);
    	}
    }
    
    private void removeConnectionLostDialog() {
	    if (connectionLostDialog != null) {
	    	connectionLostHandler.removeCallbacks(animateConnectionLostScreen);
	    	connectionLostDialog.dismiss();
	    	connectionLostDialog = null;
	    }
    }
	
	public void showSplashScreen() {
		if (splashDialog == null) {
		    splashDialog = new Dialog(this, R.style.SplashScreenTheme);
		    splashDialog.setContentView(R.layout.activity_splash_screen);
		    splashDialog.setCancelable(false);
		    splashDialog.show();
	
		    counter = 1;
		    loadingHandler.postDelayed(animateSplashScreen, 800);
		}
	}
	public void removeSplashScreen() {
	    if (splashDialog != null) {
	    	loadingHandler.removeCallbacks(animateSplashScreen);
	    	splashDialog.dismiss();
	    	splashDialog = null;
	    }
	}
	private Runnable animateSplashScreen = new Runnable() {
	      public void run() {
	    	TextView text = (TextView) splashDialog.findViewById(R.id.splashscreen_loading_dots);
	    	
	    	switch (counter) {
			case 2:
				text.setText(two);
				break;
			case 3:
				text.setText(three);
				break;
			case 4:
				text.setText(four);
				break;
			case 5:
				text.setText(five);
				break;
			default:
				text.setText(one);
				break;
			}
	    	if(counter < 5)
	    		counter++;
	    	else
	    		counter = 1;
	    	
	    	loadingHandler.postDelayed(animateSplashScreen, 800);
	      }
	};
	private Runnable animateConnectionLostScreen = new Runnable() {
	      public void run() {
	    	TextView text = (TextView) connectionLostDialog.findViewById(R.id.splashscreen_loading_dots);
	    	
	    	switch (counter) {
			case 2:
				text.setText(two);
				break;
			case 3:
				text.setText(three);
				break;
			case 4:
				text.setText(four);
				break;
			case 5:
				text.setText(five);
				break;
			default:
				text.setText(one);
				break;
			}
	    	if(counter < 5)
	    		counter++;
	    	else
	    		counter = 1;
	    	
	    	connectionLostHandler.postDelayed(animateConnectionLostScreen, 200);
	    }
	};
	
	public void startDesktop() {
		FragmentManager fragmentManager = getSupportFragmentManager();
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		if(currentFragment!=null) {
			fragmentTransaction.hide(currentFragment);
		}
		if(loginFragment!=null) {
			fragmentTransaction.remove(loginFragment);
		}
		if(desktopFragment==null||!backgroundIsOK) {
			desktopFragment = new DesktopFragment();
			fragmentTransaction.replace(R.id.MainLayout, desktopFragment,"desktop");
		}
		else {
		}
		fragmentTransaction.show(desktopFragment);
		currentFragment=desktopFragment;
		fragmentTransaction.commit();
	}
	public void startDesktop(String lang) {
		if(lang!=null) {
			Locale locale = new Locale(lang);
			Locale.setDefault(locale);
			Configuration config = new Configuration();
			config.locale = locale;
			getBaseContext().getResources().updateConfiguration(config,
			      getBaseContext().getResources().getDisplayMetrics());			
		}
		startDesktop();
	}
	
	public void startApp(String appUrl, int appId, String appLabel) {
		FragmentManager fragmentManager = getSupportFragmentManager();
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		Fragment appFragment;
		if(apps.get(appId)==null) {
			showLoadingDialog(appLabel, appsIcons.get(appId));
			appFragment = new AppFragment();
			Bundle args = new Bundle();
			args.putString("com.celebriosoftware.client.app.url", appUrl);
			args.putString("com.celebriosoftware.client.app.label", appLabel);
			args.putInt("com.celebriosoftware.client.app.id", appId);
			appFragment.setArguments(args);
			apps.put(appId, appFragment);
			fragmentTransaction.add(R.id.MainLayout, appFragment,String.valueOf(appId));
		}
		else {
			appFragment = apps.get(appId);
		}
		appFragment.setRetainInstance(true);
		if(currentFragment!=null) {
			fragmentTransaction.hide(currentFragment);
		}
		currentFragment=appFragment;
		fragmentTransaction.show(appFragment);
		fragmentTransaction.commit();
	}	
    
	public int getSpeakerState() {
		AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
		Integer volume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
		Integer maxVol = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		int volumeLevel = Math.round( (float)volume/maxVol*4 ); // rescale volume to 0-4
		return volumeLevel;
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		//volume change up
	    if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && event.getAction() == KeyEvent.ACTION_DOWN) {
	    	AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
	    	am.adjustVolume(AudioManager.ADJUST_RAISE, AudioManager.FLAG_PLAY_SOUND);
			Integer volume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
			Integer maxVol = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
			int volumeLevel = Math.round( (float)volume/maxVol*4 );	//rescale volume to 0-4
			FragmentManager fragmentManager = getSupportFragmentManager();
			Fragment desktopFragment = fragmentManager.findFragmentByTag("desktop");
			if(desktopFragment!=null) {
				((DesktopFragment) desktopFragment).updateVolume(volumeLevel);
			}
	    	return true;
	    }
	    //volume change down
	    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && event.getAction() == KeyEvent.ACTION_DOWN) {
	    	AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
	    	am.adjustVolume(AudioManager.ADJUST_LOWER, AudioManager.FLAG_PLAY_SOUND);
			Integer volume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
			Integer maxVol = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
			int volumeLevel = Math.round( (float)volume/maxVol*4 ); //rescale volume to 0-4
			FragmentManager fragmentManager = getSupportFragmentManager();
			Fragment desktopFragment = fragmentManager.findFragmentByTag("desktop");
			if(desktopFragment!=null) {
				((DesktopFragment) desktopFragment).updateVolume(volumeLevel);
			}
	    	return true;
	    }
	    return super.onKeyDown(keyCode, event);
	}
	
	//Periodically fades out the native controls bar
	@SuppressLint("NewApi")
	private class Repeater implements Runnable {
		public void run() {
			//View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
	        //| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
			//| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
			//| View.SYSTEM_UI_FLAG_LOW_PROFILE
	        //| View.SYSTEM_UI_FLAG_FULLSCREEN
	        //| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //jumps back on touch :-(
			mainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
			rHandler.removeCallbacks(repeater);
			rHandler.postDelayed(this, 2000);
		}
	};
}
